#************************************************************************************
#                                                                                                  
#                                 Ex. LCD_I2C_SHT31.py                                       
#                                                                                                  
#************************************************************************************
#                                                                                                  
#  Board MCU   : RASPBERRY PI 3 MODEL B                                                         
#  Editor-IDE  : Geany 1.29                                                                       
#  Target Board Interface : ET-IOT HAT + LCD 16x2 I2C (I2C-5V) + ET-SENSOR SHT31 (I2C-3V3)                                                      
#                                                                                                                                                                                                                                             
#************************************************************************************

import smbus
import time

#--- Open I2C interface ---
bus = smbus.SMBus(1) # use Port i2c-1 


#--- Define I2C Address of LCD-PCF8574 & TEMP-SHT31 ---
#LCD_ADDR  = 0x3F # LCD I2C device address (PCF8574A)
LCD_ADDR  = 0x27 # LCD I2C device address (PCF8574)

SHT31_ADDR  = 0x44 # Temp SHT31 I2C device address

#--- Define Valiable Keep value Teme& RH ---
cTemp = 0
RH    = 0

#---Define LCD constants ----
cmm =  0  # Sent command 
data = 1  # Sent data

BL_ON  = 0x08  
BL_OFF = 0x00 
LCD_BL = 0x08

  
#---------------------------------------
#           Function-Delay
#---------------------------------------
# dy = value delay unit (ms)
#---------------------------------------
def delay_ms(dy):
	time.sleep(dy/1000.0)


#************************ LCD FUNCTION ****************************

#--------------------------------------------------------
#                  Function-Initial LCD
# -------------------------------------------------------
def init_LCD():
	# Initialise display
	lcd_write(0x33,cmm) # 110011 Initialise
	lcd_write(0x32,cmm) # 110010 Initialise
	lcd_write(0x06,cmm) # 000110 Cursor move direction
	lcd_write(0x0C,cmm) # 001100 Display On,Cursor Off, Blink Off
	lcd_write(0x28,cmm) # 101000 Data length, number of lines, font size
	lcd_write(0x01,cmm) # 000001 Clear display
   
	time.sleep(0.005)   # delay 5 ms
	lcd_BackLight(BL_ON)
    

#-----------------------------------------------------
#           Function-LCD Write Cmm or Data 
#-----------------------------------------------------
# Send byte to data pins
# byte = data
# mode = Sent Command=0=cmm or Sent Data=1=data  
#-----------------------------------------------------    
def lcd_write(byte,mode):

	Byte_High = (byte & 0xF0)|LCD_BL| mode       # Mark Data 4 Bit High and Control BL(bit3),En=0(bit2),R/W=0(bit1),RS(bit0)
	Byte_Low  = ((byte<<4) & 0xF0)|LCD_BL| mode  # Mark data 4 Bit Low and Control  BL(bit3),En=0(bit2),R/W=0(bit1),RS(bit0)

	# Sent Data 4 bit High 
	bus.write_byte(LCD_ADDR,Byte_High)  # Write data 1 Byte(data of 4bitHigh and 4Bit Low = Control)
	lcd_enable(Byte_High)               # LCD'Enable' pin

	# Sent Data 4 bit Low
	bus.write_byte(LCD_ADDR,Byte_Low)   # Write data 1 Byte(data of 4bit Low and 4Bit Low = Control)
	lcd_enable(Byte_Low)                # LCD'Enable' pin


#---------------------------------------------------
#           Function-Toggle LCD Pin Enable
#---------------------------------------------------
# byt = data & Control for LCD 1 Byte
#---------------------------------------------------
def lcd_enable(byt):
	bus.write_byte(LCD_ADDR,(byt & 0xFB))      # Mark EN=0(bit2) and write to LCD
	time.sleep(0.0005)                         # delay 500 us
	bus.write_byte(LCD_ADDR,(byt | 0x04))      # Mark EN=1(bit2) and write to LCD
	time.sleep(0.0005)                         # delay 500 us
	bus.write_byte(LCD_ADDR,(byt & 0xFB))      # Mark EN=0(Bit2) and write to LCD


#-------------------------------------------------
#            Function-ON/OFF LCD Back Light
#-------------------------------------------------
# ONF = BL_ON:0x08  or BL_OFF:0x00
# 
#-------------------------------------------------
def lcd_BackLight(ONF):
	global LCD_BL    # global valiable
	LCD_BL = ONF


#-------------------------------------------------
#            Function-Set Cursor 
#-------------------------------------------------
# colum = 0-15
# line  = 1 or 2
#-------------------------------------------------
def lcd_cursor(colum,line):
	if 	line==0x01: 
		line = 0x80 | colum
		lcd_write(line,cmm)  # Sent Cmm Set Ram Address Line1(0x00)
	if 	line==0x02:
		line = 0xC0 | colum 
		lcd_write(line,cmm)  # Sent Cmm Set Ram Address Line1(0x40)

#--------------------------------------------------------
#                  Function-Clear LCD
# ------------------------------------------------------- 
def lcd_clear():
	lcd_write(0x01,cmm)	
	

#------------------------------------------------
#             Function-Sent String 
#------------------------------------------------
# message = string
#------------------------------------------------  
def lcd_string(message):
	for i in range(len(message)):          # Loop Print message
		lcd_write(ord(message[i]),data)    # Return ASCII Code and Write data to LCD

      
#********************** END-LCD **********************


#****************** Temp SHT31 FUNCTION *********************

#----------------------------------------------
#            Function-SHT31 Write 
#----------------------------------------------
# 
# Send measurement command,        0x2C
# High repeatability measurement   0x06
#-----------------------------------------------
def SHT31_write():
 
	bus.write_i2c_block_data(SHT31_ADDR,0x2C,[0x06])

	delay_ms(500)

  
#----------------------------------------------
#            Function-SHT31 Read 
#----------------------------------------------
# 
# Read data back from 0x00(00), 6 bytes
# data = Temp MSB[0], Temp LSB[1], Temp CRC[2], Humididty MSB[3], Humidity LSB[4], Humidity CRC[5]
#----------------------------------------------
def SHT31_read():
  
	global cTemp
	global RH
  
	data = bus.read_i2c_block_data(SHT31_ADDR,0x00,6) # Read Data SHT31 6 Byte

	# Convert the data 6 Byte
	temp = data[0] * 256 + data[1]            # Total Data temp  ByteHigh and Low
	cTemp = -45 + (175 * temp / 65535.0)      # Calculate Data temp to degree
 
	humidity =  data[3] * 256 + data[4]       # Total Data humidity  Byte High and Low
	RH = (100*humidity)/65535.0               # Calculate Data humidity to Relative Humidity(%RH)


#----------------------------------------------
#       Function-Display Temp&Humidity(RH)
#----------------------------------------------
def Show_Temp():
    
	Tmp = "%.2f" %cTemp                  # Convert Temp Flot to ASCII String 
	Hum = "%.2f" %RH                     # Convert Humidity Float to ASCII String 
   

	lcd_cursor(0,1)                      # Set Cursor Colum0 ,Line1
	lcd_string("Temp:") 

	lcd_cursor(5,1)                      # Set Cursor Colum6 ,Line1
	lcd_string(Tmp)                      # Print Temp to LCD
	lcd_cursor(11,1)                     # Set Cursor Colum12 ,Line1
	lcd_string("C") 
    
	lcd_cursor(0,2)                      # Set Cursor Colum0 ,Line2
	lcd_string("Humidity:")                
   
	lcd_cursor(9,2)                      # Set Cursor Colum10 ,Line2
	lcd_string(Hum)                      # Print Humidity to LCD
	lcd_cursor(15,2)                     # Set Cursor Colum16,Line2
	lcd_string("%")                   

    
#************************ END-Temp ***********************

print ("Test ET-SENSOR SHT31")
print ("Press CTRL-C to exit")

init_LCD()   					# Initialise LCD

lcd_cursor(3,1)                 # Set Cursor Colum4 Line1
lcd_string("ET-IOT HAT")

lcd_cursor(0,2)                 # Set Cursor Colum0 ,Line2
lcd_string("---TEST SHT31---")
 
delay_ms(3000)                  # 3 second delay

lcd_clear() 		        	# Clear LCD display

try:
	while True:
		SHT31_write()
		SHT31_read()
		Show_Temp()  

except KeyboardInterrupt:
	print("End of Program")
